﻿using System;
using System.Runtime.Caching;

namespace Awaken.Utils.CacheProvider
{
    /// <summary>
    ///     提供内存缓存
    ///     <para>--------------------------</para>
    ///     <para>@Author: cnalexi@gmail.com</para>
    ///     <para>@Create: 2012/3/21</para>
    /// </summary>
    public class MemoryCacheProvider : ICacheProvider
    {
        private static volatile MemoryCacheProvider _instance;

        private static volatile ObjectCache _myCache;

        private static readonly object _locker = new object();

        private MemoryCacheProvider()
        {
        }

        /// <summary>
        ///     内存缓存实例
        /// </summary>
        public ObjectCache MyCache
        {
            get { return _myCache ?? (_myCache = MemoryCache.Default); }
        }

        /// <summary>
        ///     添加实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public void Insert<T>(string key, T t)
        {
            MyCache.Add(key, t, null);
        }

        /// <summary>
        ///     添加相应规则的实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="policy"></param>
        public void Insert<T>(string key, T t, CacheItemPolicy policy)
        {
            MyCache.Add(key, t, policy);
        }

        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return (T) MyCache.Get(key);
        }

        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="GetData"></param>
        /// <returns></returns>
        public T Get<T>(string key, Func<T> GetData)
        {
            var t = Get<T>(key);
            if (Equals(t, default(T)))
            {
                t = GetData();
                Insert(key, t);
            }
            return t;
        }

        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="Getdata"></param>
        /// <param name="policy"></param>
        /// <returns></returns>
        public T Get<T>(string key, Func<T> Getdata, CacheItemPolicy policy)
        {
            var t = Get<T>(key);

            if (Equals(t, default(T)))
            {
                t = Getdata();

                Insert(key, t, policy);
            }
            return t;
        }

        /// <summary>
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            MyCache.Remove(key);
        }

        /// <summary>
        ///  [慎用]初始化清除默认缓存
        /// </summary>
        public void Clear()
        {
            _myCache = MemoryCache.Default;
        }

        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public void Update<T>(string key, T t)
        {
            MyCache.Remove(key);

            Insert(key, t);
        }

        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <param name="policy"></param>
        public void Update<T>(string key, T t, CacheItemPolicy policy)
        {
            MyCache.Remove(key);

            Insert(key, t, policy);
        }

        /// <summary>
        ///     查询是否包含此KEY对象
        /// </summary>
        /// <param name="Key"></param>
        /// <returns></returns>
        public bool Contains(string Key)
        {
            return MyCache.Contains(Key);
        }

        /// <summary>
        ///     单例
        /// </summary>
        /// <returns></returns>
        public static MemoryCacheProvider GetInstance()
        {
            if (_instance == null)
            {
                lock (_locker)
                {
                    if (_instance == null)
                    {
                        _instance = new MemoryCacheProvider();

                        _myCache = MemoryCache.Default;

                        //System.Threading.Thread.MemoryBarrier();
                    }
                }
            }

            return _instance;
        }
    }
}